import T from "ant-design-vue/es/table/Table";
import get from "lodash.get";
import Vue from "vue";
import VueDraggableResizable from "vue-draggable-resizable";
Vue.component("vue-draggable-resizable", VueDraggableResizable);
import { resizeableTitle } from "@/utils/util";

export default {
  name: "STable",
  data() {
    this.cellcomponents = {
      header: {
        cell: (h, props, children) =>
          resizeableTitle(h, props, children, this.columns),
      },
    };
    return {
      needTotalList: [],
      selectedRows: [],
      selectedRowKeys: [],
      localLoading: false,
      localDataSource: [],
      localPagination: Object.assign({}, this.pagination),
    };
  },
  props: Object.assign({}, T.props, {
    rowKey: {
      type: [String, Function],
      default: "key",
    },
    data: {
      type: Function,
      required: true,
    },
    pageNum: {
      type: Number,
      default: 1,
    },
    pageSize: {
      type: Number,
      default: 20,
    },
    showSizeChanger: {
      type: Boolean,
      default: true,
    },
    size: {
      type: String,
      default: "small",
    },
    /**
     * alert: {
     *   show: true,
     *   clear: Function
     * }
     */
    alert: {
      type: [Object, Boolean],
      default: null,
    },
    rowSelection: {
      type: Object,
      default: null,
    },
    /** @Deprecated */
    showAlertInfo: {
      type: Boolean,
      default: false,
    },
    showPagination: {
      type: String | Boolean,
      default: "auto",
    },
    /**
     * enable page URI mode
     *
     * e.g:
     * /users/1
     * /users/2
     * /users/3?queryParam=test
     * ...
     */
    pageURI: {
      type: Boolean,
      default: false,
    },
    showTotal: {
      type: Boolean,
      default: true,
    },
  }),
  watch: {
    "localPagination.current"(val) {
      this.pageURI &&
        this.$router.push({
          ...this.$route,
          name: this.$route.name,
          params: Object.assign({}, this.$route.params, {
            pageNo: val,
          }),
        });
      // change pagination, reset total data
      this.needTotalList = this.initTotalList(this.columns);
      this.selectedRowKeys = [];
      this.selectedRows = [];
    },
    pageNum(val) {
      Object.assign(this.localPagination, {
        current: val,
      });
    },
    pageSize(val) {
      Object.assign(this.localPagination, {
        pageSize: val,
      });
    },
    showSizeChanger(val) {
      Object.assign(this.localPagination, {
        showSizeChanger: val,
      });
    },
  },
  created() {
    const { pageNo } = this.$route.params;
    const localPageNum =
      (this.pageURI && pageNo && parseInt(pageNo)) || this.pageNum;
    this.localPagination =
      (["auto", true].includes(this.showPagination) &&
        Object.assign({}, this.localPagination, {
          current: localPageNum,
          pageSize: this.pageSize,
          pageSizeOptions: ["20", "50", "100", "500"],
          showSizeChanger: this.showSizeChanger,
          onShowSizeChange: (current, pageSize) =>
            this.onShowSizeChange(current, pageSize),
          showTotal: (total, range) =>
            this.showTotal
              ? this.$ct("tablePagingTotal", "共 " + total + " 条", {
                  total: total,
                })
              : "",
          showQuickJumper: this.localPagination.showQuickJumper
            ? this.localPagination.showQuickJumper
            : true,
          hideOnSinglePage: false,
        })) ||
      false;
    this.needTotalList = this.initTotalList(this.columns);
    this.loadData();
    // loadDrag(this.columns)
  },
  methods: {
    /**
     * 表格重新加载方法
     * 如果参数为 true, 则强制刷新到第一页
     * @param Boolean bool
     */
    refresh(bool = false) {
      bool &&
        (this.localPagination = Object.assign(
          {},
          {
            current: 1,
            pageSize: this.pageSize,
          }
        ));
      this.loadData();
    },
    /**
     * 加载数据方法
     * @param {Object} pagination 分页选项器
     * @param {Object} filters 过滤条件
     * @param {Object} sorter 排序条件
     */
    getData() {
      return this.localDataSource;
    },
    /**
     * 加载数据方法
     * @param {Object} pagination 分页选项器
     * @param {Object} filters 过滤条件
     * @param {Object} sorter 排序条件
     */
    loadData(pagination, filters, sorter) {
      this.localLoading = true;
      let order = "";
      if (sorter?.order) {
        order = sorter.order == "ascend" ? "asc" : "desc";
      } else if (sorter?.field) {
        delete sorter.field;
      }
      const parameter = Object.assign(
        {
          pageNo:
            (pagination && pagination.current) ||
            (this.showPagination && this.localPagination.current) ||
            this.pageNum,
          pageSize:
            (pagination && pagination.pageSize) ||
            (this.showPagination && this.localPagination.pageSize) ||
            this.pageSize,
        },
        (sorter &&
          sorter.field && {
            sort: sorter.field,
          }) ||
          {},
        (sorter &&
          order && {
            order: order,
          }) ||
          {},
        {
          ...filters,
        }
      );
      const result = this.data(parameter);
      // 对接自己的通用数据接口需要修改下方代码中的 r.pageNo, r.totalCount, r.data
      // eslint-disable-next-line
      if (
        (typeof result === "object" || typeof result === "function") &&
        typeof result.then === "function"
      ) {
        result.then((r) => {
          this.localPagination =
            (this.showPagination &&
              Object.assign({}, this.localPagination, {
                current: r.pageNo ? r.pageNo : 0, // 返回结果中的当前分页数
                total: r.totalCount ? r.totalCount : 0, // 返回结果中的总记录数
                showSizeChanger: this.showSizeChanger,
                pageSize:
                  (pagination && pagination.pageSize) ||
                  this.localPagination.pageSize,
              })) ||
            false;
          // 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页
          if (r.length !== undefined && !r.rows) {
            r.rows = null;
          } else if (!r.rows || r.rows === null) {
            r.rows = [];
          }
          if (
            (Number(r.rows) === 0 || Number(r) === 0) &&
            this.showPagination &&
            this.localPagination.current > 1
          ) {
            this.localPagination.current--;
            this.loadData();
            return;
          }
          // 这里用于判断接口是否有返回 r.totalCount 且 this.showPagination = true 且 pageNo 和 pageSize 存在 且 totalCount 小于等于 pageNo * pageSize 的大小
          // 当情况满足时，表示数据不满足分页大小，关闭 table 分页功能
          try {
            if (
              ["auto", true].includes(this.showPagination) &&
              r.totalCount <= r.pageNo * this.localPagination.pageSize
            ) {
              this.localPagination.hideOnSinglePage = false; //true  少于一页数据会隐藏分页
            }
          } catch (e) {
            this.localPagination = false;
          }
          this.localDataSource = r.rows ? r.rows : r; // 返回结果中的数组数据
          this.localLoading = false;
        });
      }
    },
    initTotalList(columns) {
      const totalList = [];
      columns &&
        columns instanceof Array &&
        columns.forEach((column) => {
          column.ellipsis = true;
          if (column.needTotal) {
            totalList.push({
              ...column,
              total: 0,
            });
          }
        });

      return totalList;
    },
    // 切换页数
    onShowSizeChange(current, pageSize) {
      const pager = { ...this.localPagination };
      pager.pageSize = pageSize;
      this.localPagination = pager;
      // this.loadData()
    },
    /**
     * 用于更新已选中的列表数据 total 统计
     * @param selectedRowKeys
     * @param selectedRows
     */
    updateSelect(selectedRowKeys, selectedRows) {
      this.selectedRows = selectedRows;
      this.selectedRowKeys = selectedRowKeys;
      const list = this.needTotalList;
      this.needTotalList = list.map((item) => {
        return {
          ...item,
          total: selectedRows.reduce((sum, val) => {
            const total = sum + parseInt(get(val, item.dataIndex));
            return isNaN(total) ? 0 : total;
          }, 0),
        };
      });
    },
    /**
     * 清空 table 已选中项
     */
    clearSelected() {
      if (this.rowSelection) {
        this.rowSelection.onChange([], []);
        this.updateSelect([], []);
      }
    },
    /**
     * 处理交给 table 使用者去处理 clear 事件时，内部选中统计同时调用
     * @param callback
     * @returns {*}
     */
    renderClear(callback) {
      if (this.selectedRowKeys.length <= 0) return null;
      return (
        <a
          style="margin-left: 24px"
          onClick={() => {
            callback();
            this.clearSelected();
          }}
        >
          {" "}
          清空{" "}
        </a>
      );
    },
    rowClick(record, index) {
      // 数据表格行点击事件
      const that = this;
      return {
        on: {
          click: (event) => {
            if (that.rowSelection) {
              that.rowSelection.selectedRowKeys = [];
              that.rowSelection.selectedRowKeys.push(record[that.rowKey]);
              that.$emit(
                "rowClick",
                record,
                that.rowSelection.selectedRowKeys,
                index
              );
            } else {
              that.$emit("rowClick", record, index);
            }
          },
        },
      };
    },
    renderAlert() {
      // 绘制统计列数据
      const needTotalItems = this.needTotalList.map((item) => {
        return (
          <span style="margin-right: 12px">
            {" "}
            {item.title}
            总计{" "}
            <a style="font-weight: 600">
              {" "}
              {!item.customRender
                ? item.total
                : item.customRender(item.total)}{" "}
            </a>{" "}
          </span>
        );
      });

      // 绘制 清空 按钮
      const clearItem =
        typeof this.alert.clear === "boolean" && this.alert.clear
          ? this.renderClear(this.clearSelected)
          : this.alert !== null && typeof this.alert.clear === "function"
          ? this.renderClear(this.alert.clear)
          : null;

      // 绘制 alert 组件
      return (
        <a-alert showIcon={true} style="margin-bottom: 16px">
          <template slot="message">
            <span style="margin-right: 12px">
              {" "}
              已选择:{" "}
              <a style="font-weight: 600"> {this.selectedRows.length} </a>
            </span>{" "}
            {needTotalItems} {clearItem}{" "}
          </template>{" "}
        </a-alert>
      );
    },
  },

  render() {
    const props = {};
    const localKeys = Object.keys(this.$data);
    const showAlert =
      (typeof this.alert === "object" &&
        this.alert !== null &&
        this.alert.show &&
        typeof this.rowSelection.selectedRowKeys !== "undefined") ||
      this.alert;
    Object.keys(T.props).forEach((k) => {
      const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(
        1
      )}`;
      if (localKeys.includes(localKey)) {
        props[k] = this[localKey];
        return props[k];
      }
      if (k === "rowSelection") {
        if (showAlert && this.rowSelection) {
          // 如果需要使用alert，则重新绑定 rowSelection 事件
          props[k] = {
            ...this.rowSelection,
            selectedRows: this.selectedRows,
            selectedRowKeys: this.selectedRowKeys,
            onChange: (selectedRowKeys, selectedRows) => {
              this.updateSelect(selectedRowKeys, selectedRows);
              typeof this[k].onChange !== "undefined" &&
                this[k].onChange(selectedRowKeys, selectedRows);
            },
          };
          return props[k];
        } else if (!this.rowSelection) {
          // 如果没打算开启 rowSelection 则清空默认的选择项
          props[k] = null;
          return props[k];
        }
      }
      this[k] && (props[k] = this[k]);
      return props[k];
    });
    const table = (
      <a-table
        {...{ props, scopedSlots: { ...this.$scopedSlots } }}
        onChange={this.loadData}
        components={this.cellcomponents}
        onExpand={(expanded, record) => {
          this.$emit("expand", expanded, record);
        }}
        customRow={this.rowClick}
      >
        {" "}
        {Object.keys(this.$slots).map((name) => (
          <template slot={name}> {this.$slots[name]} </template>
        ))}{" "}
      </a-table>
    );
    return (
      <div class="table-wrapper">
        {" "}
        {showAlert ? this.renderAlert() : null} {table}{" "}
      </div>
    );
  },
};
